package com.liull.netty.nio.handler;

import java.nio.charset.Charset;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * @Author: liull
 * @Description: 理解入站 出站处理器中消息的流转顺序
 * @Date: Created in 16:35 2021/7/24
 * @Modified By:
 */
// 2021-07-24 22:07:00.153 [nioEventLoopGroup-3-1] - handler 1 execute
// 2021-07-24 22:07:00.155 [nioEventLoopGroup-3-1] - handler 2 execute
// 2021-07-24 22:07:00.155 [nioEventLoopGroup-3-1] - handler 3 execute
// 2021-07-24 22:07:00.155 [nioEventLoopGroup-3-1] - handler 6 execute
// 2021-07-24 22:07:00.155 [nioEventLoopGroup-3-1] - handler 5 execute
// 2021-07-24 22:07:00.155 [nioEventLoopGroup-3-1] - handler 4 execute
@Slf4j
public class TestHandlerServer {
    public static void main(String[] args) {
        // 添加一个DefaultEventLoopGroup 处理除IO事件之外的其他事件
        new ServerBootstrap()
                .group(new NioEventLoopGroup(1), new NioEventLoopGroup(2)).channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel channel) throws Exception {
                        // handler顺序 head->h1->h2->tail
                        channel.pipeline()
                                // 下面是三个入站处理器
                                .addLast("handler1", new ChannelInboundHandlerAdapter() {
                                    @Override
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                        log.debug("handler 1 execute");
                                        final ByteBuf buf = (ByteBuf) msg;
                                        final String s = buf.toString(Charset.forName("utf-8"));
                                        // 传递给下一个InboundHandler
                                        super.channelRead(ctx, s);
                                    }
                                }).addLast("handler2", new ChannelInboundHandlerAdapter() {
                                    @Override
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                        log.debug("handler 2 execute");
                                        // 因此这块获取的msg是String类型
                                        log.debug("handler 2 msg  {}", msg);
                                        // 再转换为一个对象
                                        super.channelRead(ctx, new Student((String) msg));
                                    }
                                })
                                .addLast("handler3", new ChannelInboundHandlerAdapter() {
                                    @Override
                                    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                        log.debug("handler 3 execute");
                                        super.channelRead(ctx, msg);
                                        // 此处应该为Student 还可以继续处理下去 。。。。。
                                        log.debug("handler 3 msg {}", msg);
                                        // channel.writeAndFlush(ctx.alloc().buffer().writeBytes("server...".getBytes()));
                                        // 此处如果使用 ctx.writeAndFlush是无法触发执行下面是三个出战处理器
                                        // 因为它是从当前handler倒着往前去寻找出战处理器
                                        // handler顺序 head->h1->h2->h3->h4->h5->h6->tail 显然h3之前没有出战处理器
                                        // 而channel是从tail往前
                                        ctx.writeAndFlush(ctx.alloc().buffer().writeBytes("server...".getBytes()));
                                    }
                                })
                                // 下面是三个出战处理器
                                .addLast("handler4", new ChannelOutboundHandlerAdapter() {
                                    @Override
                                    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                                        log.debug("handler 4 execute");
                                        super.write(ctx, msg, promise);
                                    }
                                })
                                .addLast("handler5", new ChannelOutboundHandlerAdapter() {
                                    @Override
                                    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                                        log.debug("handler 5 execute");
                                        super.write(ctx, msg, promise);
                                    }
                                })
                                .addLast("handler6", new ChannelOutboundHandlerAdapter() {
                                    @Override
                                    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
                                        log.debug("handler 6 execute");
                                        super.write(ctx, msg, promise);
                                    }
                                });

                    }
                }).bind(8989);

    }

    @Data
    @AllArgsConstructor
    static class Student {
        private String name;
    }
}
